package com.maker.mcp.client.service.impl;


import cn.hutool.json.JSONUtil;
import com.maker.mcp.client.bean.ChatEntity;
import com.maker.mcp.client.bean.ChatResponseEntity;
import com.maker.mcp.client.bean.SearchResult;
import com.maker.mcp.client.enums.SSEMsgType;
import com.maker.mcp.client.service.ChatService;
import com.maker.mcp.client.service.SearXngService;
import com.maker.mcp.client.utils.SSEserver;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.document.Document;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ChatServiceImpl implements ChatService {

    @Resource
    private SearXngService searXngService;

    private final Integer CHAT_HISTORY_SIZE = 10;


    private static final String SYSTEM_PROMPT_RAG = """
                                                    基于上下文的知识库内容回答问题：
                                                    【上下文】
                                                    {context}
                                                    【问题】
                                                    {question}
                                                    【输出】
                                                    如何没有查到，请回复：未查找到。
                                                    如果有查到，请回复具体的内容。注意：不相关的近似内容不必提到。
                                                """;
    private static final String SYSTEM_PROMPT_SEARXNG = """
                                                    你是一个互联网搜索大师，请基于以下互联网返回的结果作为上下文，根据你的理解结合用户的提问综合后，生成并且输出专业的回答：
                                                    【上下文】
                                                    {context}
                                                    【问题】
                                                    {question}
                                                    【输出】
                                                    如何没有查到，请回复：未查找到。
                                                    如果有查到，请回复具体的内容。
                                           """;
    private static final String SYSTEM_PROMPT = """
                                                    你是一个非常聪明的软件架构师，
                                                    可以帮我设计很过架构，我为你
                                                    取一个名字'神奇侠'
                                                """;
    @Autowired
    private ChatClient chatClient;
    @Autowired
    private ChatMemory chatMemory;

//    public ChatServiceImpl(ChatClient.Builder chatClientBuilder , ToolCallbackProvider tools,ChatMemory chatMemory) {
//        this.chatClient = chatClientBuilder
//                            .defaultToolCallbacks( tools)
////                            .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
//                            .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
//                            .defaultSystem(SYSTEM_PROMPT)
//                            .build();
//    }

    @Override
    public Flux<String> chat(String memoryId, String message) {


        Flux<String> content = chatClient.prompt()
                .user(message)
                .advisors(advisor -> advisor.param(chatMemory.CONVERSATION_ID, memoryId))
                .stream().content();
        return content;
    }
    @Override
    public String chatTest(String prompt) {
       return  chatClient.prompt(prompt).call().content();
    }

    @Override
    public Flux<ChatResponse> streamChat(String prompt) {
        Flux<ChatResponse> chatResponseFlux = chatClient.prompt(prompt).stream().chatResponse();
        return chatResponseFlux;
    }

    @Override
    public Flux<String> streamStrChat(String prompt) {
        return chatClient.prompt(prompt).stream().content();
    }



    @Override
    public void doChat(ChatEntity chatEntity) {
        String userId = chatEntity.getCuurentUserName();
        String prompt = chatEntity.getMessage();
        String chatId = chatEntity.getChatId();

        Flux<String>   stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list =stringFlux.toStream().map(chatResposne -> {
            String content =chatResposne.toString() ;
            //msgType 前端传值为add
            SSEserver.sendMsg(userId,content, SSEMsgType.ADD);
            log.info("用户{}的会话内容：{}",userId,content);
            return content;
        }).collect(Collectors.toList());
        //TODO 可以将会话内容保存到数据库，作为拓展
        String fullCollect = list.stream().collect(Collectors.joining());

        ChatResponseEntity chatResponseEntity = new ChatResponseEntity(fullCollect, chatId);

        SSEserver.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);
    }



    /**
     * rag知识库检索汇总
     * @param chatEntity
     * @param documentList
     */
    @Override
    public void doChatRagSearch(ChatEntity chatEntity, List<Document> documentList) {
        String userId = chatEntity.getCuurentUserName();
        String question = chatEntity.getMessage();
        String chatId = chatEntity.getChatId();
        String context=null;
        //构建提示词
        if(documentList!=null&&documentList.size()>0){
            context = documentList.stream()
                                .map(Document::getText)
                                .collect(Collectors.joining("\n"));
        }

        Prompt prompt = new Prompt(SYSTEM_PROMPT_RAG
                                    .replace("{context}",context)
                                    .replace("{question}",question));

        Flux<String>   stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list =stringFlux.toStream().map(chatResposne -> {
            String content =chatResposne.toString() ;
            //msgType 前端传值为add
            SSEserver.sendMsg(userId,content, SSEMsgType.ADD);
            log.info("用户{}的会话内容：{}",userId,content);
            return content;
        }).collect(Collectors.toList());
        //TODO 可以将会话内容保存到数据库，作为拓展
        String fullCollect = list.stream().collect(Collectors.joining());

        ChatResponseEntity chatResponseEntity = new ChatResponseEntity(fullCollect, chatId);

        SSEserver.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);
    }

    /**
     * rag知识库检索汇总
     * @param chatEntity
     * @param documentList
     */
    @Override
    public Flux<String>  doChatRagSearchV2(ChatEntity chatEntity, List<Document> documentList) {
        String userId = chatEntity.getCuurentUserName();
        String question = chatEntity.getMessage();
        String chatId = chatEntity.getChatId();
        String context=null;
        //构建提示词
        if(documentList!=null&&documentList.size()>0){
            context = documentList.stream()
                    .map(Document::getText)
                    .collect(Collectors.joining("\n"));
        }

        Prompt prompt = new Prompt(SYSTEM_PROMPT_RAG
                .replace("{context}",context)
                .replace("{question}",question));

//        Flux<String>   stringFlux = chatClient.prompt(prompt).stream().content();
        Flux<String> content = chatClient.prompt(prompt)
                .advisors(advisor -> advisor.param(chatMemory.CONVERSATION_ID, chatId))
                .stream().content();

        return content;
    }
    /**
     *基于searxng的实时联网检索
     * @param chatEntity
     */
    @Override
    public void doInternetSearch(ChatEntity chatEntity) {
        String userId = chatEntity.getCuurentUserName();
        String question = chatEntity.getMessage();
        String chatId = chatEntity.getChatId();
        List<SearchResult> searchResults = searXngService.search(question);
        //构建提示词
        StringBuilder context = new StringBuilder();
        searchResults.forEach(searchResult -> {
            context.append(String.format("<context>\n[来源] s% [摘要] s% \n</context>\n",
                            searchResult.getUrl(),
                            searchResult.getContent()));
        });

        Prompt prompt = new Prompt(SYSTEM_PROMPT_SEARXNG
                .replace("{context}",context.toString())
                .replace("{question}",question));
        log.info("互联网搜索提示词：{}",prompt.getContents());
        Flux<String>   stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list =stringFlux.toStream().map(chatResposne -> {
            String content =chatResposne.toString() ;
            //msgType 前端传值为add
            SSEserver.sendMsg(userId,content, SSEMsgType.ADD);
            log.info("用户{}的会话内容：{}",userId,content);
            return content;
        }).collect(Collectors.toList());
        //TODO 可以将会话内容保存到数据库，作为拓展
        String fullCollect = list.stream().collect(Collectors.joining());

        ChatResponseEntity chatResponseEntity = new ChatResponseEntity(fullCollect, chatId);

        SSEserver.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);
    }
}
